<!--
功能：页面搜索
作者：Maoxiangdong
邮箱：862755519@qq.com
时间：2023-12-01 09:08:17
-->
<template>
  <div class="page-search-container">
    <a-form
      ref="formRef"
      :colon="searchOptions.colon"
      :disabled="searchOptions.disabled"
      :labelAlign="searchOptions.labelAlign"
      :layout="searchOptions.layout"
      :label-col="labelCol"
      :hideRequiredMark="searchOptions.hideRequiredMark"
      :model="searchOptions.model"
      :rules="searchOptions.rules"
      class="form-container"
    >
      <a-row :gutter="15">
        <!-- 生成动态表单 -->
        <template v-for="(item, index) in searchOptions.modelItem" :key="index">
          <a-col :span="item.span">
            <a-form-item :label="item.title" :name="item.field" class="form-container-item">
              <!-- 文本输入框 -->
              <template v-if="item.type == 'input'">
                <a-input
                  v-model:value="searchOptions.model[item.field]"
                  :maxlength="item.maxlength"
                  :allowClear="item.allowClear"
                  :placeholder="item.placeholder"
                  style="width: 100%"
                />
              </template>
              <!-- 数字输入框 -->
              <template v-if="item.type == 'inputNumber'">
                <a-input-number
                  v-model:value="searchOptions.model[item.field]"
                  :min="item.min"
                  :max="item.max"
                  :allowClear="item.allowClear"
                  :placeholder="item.placeholder"
                  style="width: 100%"
                />
              </template>
              <!-- 选择器 -->
              <template v-if="item.type == 'select'">
                <a-select
                  v-model:value="searchOptions.model[item.field]"
                  :showSearch="item.showSearch"
                  :allowClear="item.allowClear"
                  :placeholder="item.placeholder"
                  :mode="item.mode"
                  style="width: 100%"
                >
                  <a-select-option
                    v-for="element in item.dataOptions"
                    :value="element[item.valueField]"
                    :key="element[item.valueField]"
                  >
                    {{ element[item.labelField] }}
                  </a-select-option>
                </a-select>
              </template>
              <!-- 日期选择 -->
              <template v-if="item.type == 'datePicker'">
                <a-date-picker
                  v-model:value="searchOptions.model[item.field]"
                  :showTime="item.showTime"
                  :allowClear="item.allowClear"
                  :placeholder="item.placeholder"
                  :mode="item.mode"
                  style="width: 100%"
                />
              </template>
            </a-form-item>
          </a-col>
        </template>
        <a-col class="gutter-row" :span="4">
          <a-form-item label="" class="form-container-item">
            <a-button type="primary" @click="handleSubmit">查询</a-button>
            <a-button style="margin-left: 10px" @click="handleReset">重置</a-button>
          </a-form-item>
        </a-col>
      </a-row>
    </a-form>
  </div>
</template>

<script setup>
import { computed, reactive, ref, watch } from 'vue'
import { message } from 'ant-design-vue'
const props = defineProps({
  // 父级传入的搜索表单配置属性
  pageSearchOptions: {
    type: Object,
    default: () => {}
  }
})
// 搜索表单配置属性
const searchOptions = reactive({
  // 配置 Form.Item 的 colon 的默认值 (只有在属性 layout 为 horizontal 时有效)
  colon: false,
  // 设置表单组件禁用，仅对 antdv 组件有效
  disabled: false,
  // 隐藏所有表单项的必选标记
  hideRequiredMark: true,
  // label 标签的固定宽度
  labelWidth: '65px',
  // label 标签的文本对齐方式 (只有在属性 layout 为 horizontal 时有效)
  labelAlign: 'left',
  // 布局模式 'horizontal'|'vertical'|'inline'
  layout: 'horizontal',
  // 表单数据对象需与表单数据配置项的field一致
  model: {
    input: null,
    inputNumber: null,
    select: null,
    datePicker: null
  },
  // 表单验证规则
  rules: {
    input: [{ required: true, message: '表单内容不能为空', trigger: 'blur' }],
    inputNumber: [{ required: true, message: '表单内容不能为空', trigger: 'blur' }]
  },
  // 表单数据配置项
  modelItem: [
    // 文本输入框
    {
      type: 'input', // 表单类型
      field: 'input', // 字段属性key
      title: '文本输入', // 字段名称
      span: 4, // 栅格占位格数，为 0 时相当于 display: none
      placeholder: '请输入文本', // 占位文字
      allowClear: false, // 可以点击清除图标删除内容
      maxlength: null // 最大输入长度
    },
    // 数字输入框
    {
      type: 'inputNumber', // 表单类型
      field: 'inputNumber', // 字段属性key
      title: '数字输入', // 字段名称
      span: 4, // 栅格占位格数，为 0 时相当于 display: none
      placeholder: '请输入数字', // 占位文字
      max: null, // 最大值
      min: null // 最小值
    },
    // 选择器
    {
      type: 'select', // 表单类型
      field: 'select', // 字段属性key
      title: '选择内容', // 字段名称
      span: 4, // 栅格占位格数，为 0 时相当于 display: none
      placeholder: '请选择内容', // 占位文字
      allowClear: false, // 可以点击清除图标删除内容
      showSearch: true, // 是否可搜索
      dataOptions: [
        { value: 'beijing', label: '北京' },
        { value: 'shanghai', label: '上海' },
        { value: 'nanjing', label: '南京' },
        { value: 'hangzhou', label: '杭州' },
        { value: 'kunming', label: '昆明' }
      ], // 数据源选项配置 array<{value, label, [disabled, key, title]}>
      valueField: 'value', // 数据源value键名称
      labelField: 'label', // 数据源label键名称
      mode: null // 设置 Select 的模式为多选或标签 'multiple' | 'tags' | 'combobox'
    },
    // 日期选择
    {
      type: 'datePicker', // 表单类型
      field: 'datePicker', // 字段属性key
      title: '选择日期', // 字段名称
      span: 4, // 栅格占位格数，为 0 时相当于 display: none
      placeholder: '请选择日期', // 占位文字
      mode: 'date', // 日期面板的状态 time | date | month | year | decade
      showTime: false // 增加时间选择功能
    }
  ]
})
// 表单对象
const formRef = ref()
// label配置属性
const labelCol = computed(() => {
  return { style: { width: searchOptions.labelWidth } }
})
// 派生数据
const emits = defineEmits(['onSubmit', 'onReset'])
// 查询
const handleSubmit = () => {
  formRef.value
    .validate()
    .then(() => {
      console.log('验证成功')
      emits('onSubmit', searchOptions.model)
    })
    .catch(() => {
      message.error('表单必填项不能为空')
    })
}
// 重置
const handleReset = () => {
  formRef.value.resetFields()
  emits('onReset', searchOptions.model)
}
// 监听数据变化
watch(
  props.pageSearchOptions,
  (newValue) => {
    if (newValue) {
      for (const key in newValue) {
        if (newValue[key] !== null && newValue[key] !== undefined && newValue[key] !== undefined) {
          searchOptions[key] = newValue[key]
        }
      }
    }
  },
  { immediate: true, deep: true }
)
</script>
<style lang="scss" scoped>
.page-search-container {
  padding: 15px 15px 0px 15px;
  background-color: #ffffff;
  box-shadow: 0 0 6px 0 rgba(51, 51, 51, 0.08);
  border-radius: 4px;
  .form-container {
    // border: 1px solid red;
    &-item {
      margin-bottom: 15px;
    }
  }
}
</style>
